"""
将charles导出的json格式转为postman支持的格式
支持2种格式，1.summary json  2.session json
"""
import json
import uuid
import os
import xmltodict
class charlesToJson:
    postmanJson = {
        "info": {
            "_postman_id": "",  # uuid
            "name": "",  # 文件夹名称
            "schema": ""  # 未知
        },
        "item": [
            {
                "name": "",  # 接口名称
                "event": [],  # Tests，已知有：断言
                "protocolProfileBehavior": {},  # 设置里面内容，已知ssl校验
                "request": {  # 请求信息、方法、头、内容、地址
                    "method": "",
                    "header": [
                        {
                            "key": "",
                            "name": "",  # 和key的值一样
                            "value": "",
                            "type": "text"
                        }
                    ],
                    "body": {
                        "mode": "",  # 参数形式
                        "urlencoded": [
                            {
                                "type": "text",
                                "key": "version",
                                "value": "1.0"
                            }
                        ]
                        # 参数内容
                    },
                    "url": {
                        "raw": "",  # 完整地址
                        "host": "",  # 域名
                        "path": [
                            ""  # 除域名外的路径
                        ]
                    },
                    "response": []  # 响应内容，可以为空
                }
            }
        ]
    }

    def sessionJsonToPostman(self):
        # 获取当前所有以".chlsj" 结尾的文件路径
        print('os.walk(os.getcwd():',os.walk(os.getcwd()))
        chlsjList = []
        for root, dirs, files in os.walk(os.getcwd()):
            print(root, dirs, files)
            for file in files:
                # print('file:', file)
                if os.path.splitext(file)[1] == '.chlsj':
                    # print('file:', file)
                    chlsjList.append(file)
            # 因为只取当前目录的文件，所以只循环一次，那为什么要循环呢？因为generate对象除了循环我也不知道咋取值了
            break
        print(chlsjList)
        for filename in chlsjList:
            # 读取文件
            with open("./{}".format(filename),'r',encoding='utf-8') as f:
            # with open("./summarySession.chlsj", 'r', encoding='utf-8') as f:
                text=f.read()
                sessionList=json.loads(text)
                # print(sessionList)

                #根据uuid生成_postman_id
                _postman_id=str(uuid.uuid1())
                print('_postman_id:',_postman_id)
                # name,导入postman后的文件名称
                name=filename.split('.')[0]
                # schema，不知道啥玩意
                schema= "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
                #组成info
                info={
                    "_postman_id": _postman_id,
                    "name": name,
                    "schema": schema
                }
                """
                组成item，item中每一个元素就是一个请求
                """

                # mimeType 映射,待完善，左边是charles、右边是postman
                mimeTypeDict={
                    'application/x-www-form-urlencoded':'urlencoded',
                    'application/json':'application/json'
                }
                #申明postman数据格式字典
                postmanJson= {
                    'info':info,
                    'item':[]
                }
                for item in sessionList:

                    sessionHeaders=item['request']['header']['headers']
                    postmanHeader=[]
                    for head in  sessionHeaders:
                        key=head['name']
                        # print(key[0])
                        # 过滤header中 异常键值 1.key值以":"开头的key，去掉":"  2.过滤content-length
                        if key[0]==':':
                            key=key.split(':')[1]
                        if key=='content-length':
                            pass
                        postmanHeader.append({
                            "key": key,
                            "name": key,
                            "value": head['value'],
                            "type": "text"
                        })
                    print('postmanHeader:',postmanHeader)
                    # 从sessionJson中拿到body，并转为字典格式
                    # 判断 item['request'] 中是否存在 body
                    if 'body' in item['request'].keys():
                        sessionBody=item['request']['body']['text']
                    else:
                        sessionBody={}
                    print('sessionBody:',sessionBody)
                    # 如果 query字段 存在，转为列表存入url 字典中
                    query = []
                    if 'query' in item.keys() and item['query'] != None:
                        chralesQuery = item['query'].split('&')
                        for i in chralesQuery:
                            query.append({
                                'key':i.split('=')[0],
                                'value':i.split('=')[1]
                            })


                    # 生成postman的请求body
                    postmanBody={}
                    print("item",item['request'])
                    if 'mime-type' in item['request'].keys() or 'mimeType' in item['request'].keys():
                        print("here")
                        # 如果请求格式是json
                        if item['request']['mimeType'] =="application/json":
                            print('该请求格式是application/json')
                            postmanBody={
                                "mode": "raw",
                                "raw": sessionBody,
                                "options": {
                                    "raw": {
                                        "language": "json"
                                    }
                                }
                            }
                        # 如果请求格式是x-www-form-urlencoded
                        if item['request']['mimeType'] == "application/x-www-form-urlencoded":
                            print('该请求格式是application/x-www-form-urlencoded')
                            params = []
                            if sessionBody!={}:
                                # 将charles中的请求内容拆分为list
                                sessionBody = sessionBody.split('&')
                                for i in sessionBody:
                                    param = i.split('=')
                                    params.append({
                                        "key": param[0],
                                        "value": param[1],
                                        "type": "text"
                                    })
                            print('params:', params)
                            postmanBody = {
                                "mode": "urlencoded",
                                "urlencoded": params
                            }

                    # 把host拆分成列表
                    sessionHost=item['host']
                    postmanHost=sessionHost.split('.')
                    #把path拆分成列表
                    sessionPath = item['path']
                    postmanPath = sessionPath.split('/')
                    #删除空字符串
                    for i in postmanPath:
                        if i =='':
                            postmanPath.remove(i)
                    #完整接口请求地址
                    #判断有没有port字段存在，主要是当接口是通过ip地址形式拼接时，必须要传端口
                    if 'port' in item.keys():
                        raw=str(item['host'])+":"+str(item['port'])+item['path']
                        url = {
                            "raw": raw,  # 完整地址
                            "protocol": item['scheme'],  # 协议
                            "host": postmanHost,  # 域名
                            "port":item['port'], # 端口
                            "path": postmanPath,  # 除域名外的路径
                            "query": query  # 当请求参数是 params形式时，传入
                        }
                    else:
                        raw=str(item['host'])+item['path']
                        url = {
                            "raw": raw,  # 完整地址
                            "protocol": item['scheme'],  # 协议
                            "host": postmanHost,  # 域名
                            "path": postmanPath,  # 除域名外的路径
                            "query": query  # 当请求参数是 params形式时，传入
                        }
                    print(raw)

                    # 生成url


                    requestJson={
                        "name": item['path'],  # 接口名称,取path
                        # "event": [],  # Tests，已知有：断言，默认为空
                        "protocolProfileBehavior": {"strictSSL": False},  # 默认关闭证书校验
                        "request": {  # 请求信息、方法、头、内容、地址
                            "method": item['method'],
                            "header": postmanHeader,#请求头
                            "body": postmanBody,
                            "url": url #接口地址
                        },
                        "response": []  # 响应内容，可以为空
                    }
                    print('requestJson:',requestJson)
                    postmanJson['item'].append(requestJson)
                print('postmanJson:',postmanJson)

                #保存为json文件
                with open("./{}.postmanCollection.json".format(filename.split('.')[0]),'w',encoding='utf-8') as f:
                    f.write(json.dumps(postmanJson,ensure_ascii=False))
    # Xml 转postmanjson
    def sessionXMLToPostman(self):
        # 获取当前所有以".chlsx" 结尾的文件路径
        # print('os.walk(os.getcwd():', os.walk(os.getcwd()))
        chlsjList = []
        for root, dirs, files in os.walk(os.getcwd()):
            # print(root, dirs, files)
            for file in files:
                # print('file:', file)
                if os.path.splitext(file)[1] == '.chlsx':
                    # print('file:', file)
                    chlsjList.append(file)
            # 因为只取当前目录的文件，所以只循环一次，那为什么要循环呢？因为generate对象除了循环我也不知道咋取值了
            break
        print(chlsjList)
        for filename in chlsjList:
            # 读取文件
            with open("./{}".format(filename), 'r', encoding='utf-8') as f:
                text = f.read()
                xml_parse = xmltodict.parse(text)
                json_str = json.dumps(xml_parse, indent=1,ensure_ascii=False)
                # xml转成dict后有些key前面会带有 @ 字符，去除
                json_str = str(json_str)
                json_str = json_str.replace('\"@', '\"')
                # print('json_str:', json_str)
                json_dict = json.loads(json_str)
                transaction = json_dict['charles-session']['transaction']
                print('xml转为json后 transaction:', json.dumps(transaction,ensure_ascii=False))

                # 根据uuid生成_postman_id
                _postman_id = str(uuid.uuid1())
                print('_postman_id:', _postman_id)
                # name,导入postman后的文件名称
                name = filename.split('.')[0]
                # schema，不知道啥玩意
                schema = "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
                # 组成info
                info = {
                    "_postman_id": _postman_id,
                    "name": name,
                    "schema": schema
                }
                # 申明postman数据格式字典
                postmanJson = {
                    'info': info,
                    'item': []
                }
                sessionList=[]
                # 如果 transaction 是字典形式，转成列表再取值
                if isinstance(transaction,dict):
                    sessionList.append(transaction)
                elif isinstance(transaction,list):
                    sessionList=transaction
                for item in sessionList:
                    print(item)
                    sessionHeaders = item['request']['headers']['header']
                    postmanHeader = []
                    for head in sessionHeaders:
                        key = head['name']
                        # print(key[0])
                        # 过滤header中 异常键值 1.key值以":"开头的key，去掉":"  2.过滤content-length
                        if key[0] == ':':
                            key = key.split(':')[1]
                        if key == 'content-length':
                            pass
                        postmanHeader.append({
                            "key": key,
                            "name": key,
                            "value": head['value'],
                            "type": "text"
                        })
                    print('postmanHeader:', postmanHeader)
                    # 从sessionJson中拿到body，并转为字典格式
                    # 判断 item['request'] 中是否存在 body
                    if 'body' in item['request'].keys() :
                        print(item['request']['body'])
                        sessionBody = item['request']['body']
                    else:
                        sessionBody = {}

                    # 如果 query字段 存在，转为列表存入url 字典中
                    query = []
                    if 'query' in item.keys() and item['query'] != None:
                        chralesQuery = item['query'].split('&')
                        for i in chralesQuery:
                            query.append({
                                'key': i.split('=')[0],
                                'value': i.split('=')[1]
                            })

                    # 生成postman的请求body
                    postmanBody = {}
                    if 'mime-type' in item['request'].keys():
                        # 如果请求格式是json
                        if item['request']['mime-type'] == "application/json":
                            postmanBody = {
                                "mode": "raw",
                                "raw": sessionBody,
                                "options": {
                                    "raw": {
                                        "language": "json"
                                    }
                                }
                            }
                        # 如果请求格式是x-www-form-urlencoded
                        if item['request']['mime-type'] == "application/x-www-form-urlencoded":
                            params = []
                            if sessionBody != {}:
                                # 将charles中的请求内容拆分为list
                                sessionBody = sessionBody.split('&')
                                for i in sessionBody:
                                    param = i.split('=')
                                    params.append({
                                        "key": param[0],
                                        "value": param[1],
                                        "type": "text"
                                    })
                            print('params:', params)
                            postmanBody = {
                                "mode": "urlencoded",
                                "urlencoded": params
                            }

                    # 把host拆分成列表
                    sessionHost = item['host']
                    postmanHost = sessionHost.split('.')
                    # 把path拆分成列表
                    sessionPath = item['path']
                    postmanPath = sessionPath.split('/')
                    # 删除空字符串
                    for i in postmanPath:
                        if i == '':
                            postmanPath.remove(i)
                    requestJson = {
                        "name": item['path'],  # 接口名称,取path
                        # "event": [],  # Tests，已知有：断言，默认为空
                        "protocolProfileBehavior": {"strictSSL": False},  # 默认关闭证书校验
                        "request": {  # 请求信息、方法、头、内容、地址
                            "method": item['method'],
                            "header": postmanHeader,  # 请求头
                            "body": postmanBody,
                            "url": {
                                "raw": item['host'] + item['path'],  # 完整地址
                                "protocol": item['protocol'],  # 协议
                                "host": postmanHost,  # 域名
                                "path": postmanPath,  # 除域名外的路径
                                "query": query  # 当请求参数是 params形式时，传入
                            }
                        },
                        "response": []  # 响应内容，可以为空
                    }
                    print('requestJson:', requestJson)
                    postmanJson['item'].append(requestJson)
                print('postmanJson:', postmanJson)
                # 保存为json文件
                with open("./{}.postmanCollection.json".format(filename.split('.')[0]), 'w', encoding='utf-8') as f:
                    f.write(json.dumps(postmanJson,ensure_ascii=False))



if __name__ == '__main__':
    charlesToJson().sessionJsonToPostman()
    charlesToJson().sessionXMLToPostman()





























